#ifndef _COORD_H
#define _COORD_H

/** Fichier qui définit une classe implémentant un point de l'espace.
 *
 * Ce fichier contient la définition de la classe Coord.
 *
 * @file Coord.hpp
 *
 * @author Jean-Marc Comby
 * @author Romain Dequesne
 * @author Johan "Solo" Luisier
 * @date 19 Mars 2004
 */

#include <iostream>

/*
 * Notre classe de base est ici.
 */
#include <boost/numeric/ublas/vector.hpp>

/** Alias pour raccourcir les déclarations.
 *
 * Le type utilisé comme base implémente déjà la plupart des méthodes d'algèbre
 * linéaire, ce qui le rend très intéressant, mais le tapper est fastidieux.
 */
typedef boost::numeric::ublas::vector< double > VecteurBase;

/** Classe qui implémente un point de l'espace.
 *
 * Classe implémentant des points de l'espace. Pour se simplifier la
 * gestion de la mémoire, des interaction avec les matrices, cette
 * classe hérite maintenant des vecteur définis dans ublas (librairie
 * boost).
 *
 * @author Jean-Marc Comby
 * @author Romain Dequesne
 * @author Johan "Solo" Luisier
 *
 * @date 24 Juin 2011
 *
 * @class Coord "Coord.hpp" "Algebre/Coord.hpp"
 */
class Coord : public VecteurBase
{
protected:
    enum Statut
    {
        Inconnu = 0,
        Nul,
        Initialise,
        Infini
    };
    Statut StatutInterne;

public:
    // Constructeur
    Coord(const bool& origine = true); // Constructeur par defaut
    Coord(const double&,const double&,const double&); // Constructeur avec valeurs xyz
    Coord(const Coord&); // Constructeur de copie
    Coord( const VecteurBase& vecBoost );
    // Destructeur
    virtual~Coord();
    // Operateur pour acceder au valeur de mon tableau
    // Methode pour retourner la valeur, alias et r par moi
    const double& x() const;
    const double& y() const;
    const double& z() const;
    double r2() const;
    double r() const;

    inline bool estDefini() const { return StatutInterne != Coord::Inconnu; }
    inline bool estNul() const { return StatutInterne == Coord::Nul; }
    inline bool estInfini() const { return StatutInterne == Coord::Infini; }


    // Méthodes pour changer les coordonées
    //void set_x(const double& x);
    void setX(const double& x);
    //void set_y(const double& y);
    void setY(const double& y);
    //void set_z(const double& z);
    void setZ(const double& z);

    // affiche les 3 coordonnees
    void affiche();
    // operateur d'affectation
    Coord &operator=(const Coord&);
    Coord &operator=(const VecteurBase& vecBoost);
    // operateur de comparaison
    bool operator==(const Coord &) const;
    bool operator!=(const Coord &) const;
    Coord operator-() const;
    // operateur d'addition
    Coord operator+(const Coord&) const;
    Coord &operator+=(const Coord&);
    // operateur de soustraction par moi
    Coord operator-(const Coord&) const;
    Coord &operator-=(const Coord&);
    // operateur de multiplication
    Coord& operator*=(const double&);
    Coord operator*(const double&) const;
    Coord& operator/=(const double& scalaire);
    Coord operator/(const double& scalaire) const;
    friend Coord operator*(const double& scalaire, const Coord& pt);
    // comparaison, par moi
    bool operator<(const Coord&) const;
    // affichage, par moi
    friend std::ostream& operator<<(std::ostream&, const Coord&);
protected:
    const double& at( const unsigned& i ) const;
};

static Coord NullePart( false );

#endif
